package chatGUI;

import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JSplitPane;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JList;

import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import people.User;

/**
 * <b>Project ChatSystemG2 - INSA 4INFOA1 - 2013/2014</b>
 * <P>
 * <i>Package  chatGUI</i> <br>
 * WindowComunication is the window displayed when a user is connected. It contains one chatTab by conversation with a user.
 * <br>
 * It implements the interfaces ActionListeners, WindowListener and Observer and extends the class JFrame.
 * 
 * @author Sergio Gonzalez - Marie-Charlotte Bideaud
 */

public class WindowComunication extends JFrame implements Observer, WindowListener, ActionListener {

	private static final long serialVersionUID = 1L;

	private ChatGUI cgui;

	private JPanel panelLeft;
	private JPanel panelRigth;
	private JSplitPane splitPane;

	private JMenuBar menuBar;
	private JMenu menuDisconnect;
	private JMenuItem itemDisconnect;

	private JLabel lblTitleLeft;
	private JLabel lblTitle;
	private JButton startChat;
	private JTabbedPane tabbedPane;
	private JList list;

	private ArrayList<User> userlist = new ArrayList<User>();
	private ArrayList<ChatTab> tabList = new ArrayList<ChatTab>();

	/**
	 * Constructor for the class WindowComunication
	 * 
	 * @param cgui : ChatGUI
	 */
	public WindowComunication(ChatGUI cgui) {		
		this.cgui = cgui;
		initComponents();
	}

	/**
	 * Method to initiate a windowComunication (called when a new window is instanced). 
	 */
	private void initComponents() {		
		// Definition of the layouts and the components
		this.setLayout(new BorderLayout());
		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

		this.setMinimumSize(new Dimension(800, 600));
		this.setTitle("ChatSystem");
		this.addWindowListener(this);

		panelLeft = new JPanel();
		panelRigth = new JPanel();
		splitPane = new JSplitPane();

		this.getContentPane().add(panelLeft, BorderLayout.WEST);
		this.getContentPane().add(splitPane, BorderLayout.CENTER);
		this.getContentPane().add(panelRigth, BorderLayout.EAST);

		// initiate the menu "Disconnect" 
		this.initMenu();
		// initiates the 2 panels
		this.initPaneLeft();
		this.initPaneRight();

		this.pack();
	}

	/**
	 * Method to initiate the menu "Disconnect"
	 */
	private void initMenu(){
		menuBar = new JMenuBar();
		this.setJMenuBar(menuBar);

		menuDisconnect = new JMenu("Disconnect");
		menuBar.add(menuDisconnect);

		itemDisconnect = new JMenuItem("Disconnect");
		itemDisconnect.addActionListener(this);
		itemDisconnect.setActionCommand("disconnect");
		menuDisconnect.add(itemDisconnect);

		menuBar.add(Box.createGlue());
		lblTitle = new JLabel();
		menuBar.add(lblTitle);
	}
	
	/**
	 * Method to initiate the panelLeft (the users list)
	 */
	private void initPaneLeft(){
		panelLeft.setLayout(new BorderLayout(0,0));
		panelLeft.setBackground(Color.WHITE);
		panelLeft.setForeground(Color.WHITE);
		panelLeft.setMinimumSize(new Dimension(110, 10));
		panelLeft.setSize(new Dimension(110, 10));

		lblTitleLeft = new JLabel("Contacts: ");

		// the users list
		list = new JList();

		startChat = new JButton("Start a Chat");
		startChat.addActionListener(this);
		startChat.setActionCommand("start");

		splitPane.setLeftComponent(panelLeft);
		panelLeft.add(lblTitleLeft, BorderLayout.NORTH);
		panelLeft.add(list, BorderLayout.CENTER);
		panelLeft.add( new JScrollPane(list));
		panelLeft.add(startChat, BorderLayout.SOUTH);

	}
	
	/**
	 * Method to initiate the panel right (where the chat tabs are)
	 */
	private void initPaneRight(){
		panelRigth.setLayout(new BorderLayout(0,0));
		panelRigth.setSize(new Dimension(200, 300));
		panelRigth.setMinimumSize(new Dimension(200, 300));
		
		tabbedPane = new JTabbedPane();
		tabbedPane.setSize(new Dimension(200, 300));
		tabbedPane.setMinimumSize(new Dimension(200, 300));
		tabbedPane.setAutoscrolls(true);
		
		// The following line enables to use scrolling tabs.
		tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
		
		// Add the tabbed pane to this panel.
		splitPane.setRightComponent(panelRigth);
		panelRigth.add(tabbedPane, BorderLayout.CENTER);
		
	}
	
	/**
	 * Getter of the lblTitle
	 * 
	 * @return JLabel
	 */
	public JLabel getLblTitle() {
		return lblTitle;
	}
	
	/**
	 * Method called to display the window
	 */
	public void display() {
		this.setVisible(true);		
	}
	
	/**
	 * Method called to close the window
	 */
	public void close() {
		this.dispose();		
	}
	
	/**
	 * Method called to clear the list and the tabs
	 */
	public void clear(){
		userlist.clear();
		tabList.clear();
		tabbedPane.removeAll();
	}
	
	/**
	 * Method called when an observable notifies his observers of a change in an object
	 * 
	 * @param arg0 : Observable
	 * @param obj : Object
	 */
	public void update(Observable arg0, Object obj) {
		// if the object in the notification is an ArrayList
		if (obj instanceof ArrayList) {
			// update the list of the connected users in the panel left
			userlist = (ArrayList<User>) obj;
			cgui.performNewUser( userlist, list);
			this.revalidate();
		}
		// if the object in the notification is a User
		if (obj instanceof User) {
			User user = (User) obj;
			
			switch (user.getType()) {
			// different types of the user's status
            case DISCONNECT:
            	cgui.performDeleteUser(user, tabList, tabbedPane);
                break;
                         
            case TEXT: 
            	if (! cgui.performMsgReceived(user, tabList)) {
					tabList = cgui.clickStartChatButton(user, tabList, tabbedPane);
					cgui.performMsgReceived(user, tabList);
				}
                break;
                
            case FILEREQUEST:
            	cgui.performAnswerRequest(user);
                break;
                
            case FILEANSWER:
            	if (user.isAnswer()) {
            		if (! cgui.performAccepted(user, tabList)) {
    					tabList = cgui.clickStartChatButton(user, tabList, tabbedPane);
    					cgui.performAccepted(user, tabList);
    				}
            	} else {
            		if (! cgui.performRefused(user, tabList)) {
    					tabList = cgui.clickStartChatButton(user, tabList, tabbedPane);
    					cgui.performRefused(user, tabList);
    				}
            	}
                break;
            
            case FILE:
            	cgui.performFileReceived();
                break;
                
			default:	break;
			
			}
			this.revalidate();
		}
	}
	
	/**
	 * Method called when a button is pressed by the local user
	 * 
	 * @param e : ActionEvent
	 */
	public void actionPerformed(ActionEvent e) {
		// if the users presses the start chat button
		if (e.getActionCommand().equals("start")) {
			if (cgui.selectUsers(list)) {
				int[] arrayUsers = list.getSelectedIndices();
				User firstUser = userlist.get(arrayUsers[0]);
				tabList = cgui.clickStartChatButton(firstUser, tabList, tabbedPane);
			}
		}
		
		// if the user presses the disconnect button
		if (e.getActionCommand().equals("disconnect")) {
			int option = JOptionPane.showConfirmDialog(null, "Are you sure to want to disconnect ?", "Disconnect", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
			if(option == JOptionPane.OK_OPTION)
			{
				// clear the history
				clear();
				// disconnect the user from the chat
				cgui.clickDisconnectButton();
			}
		}
	}
	
	/**
	 * Method called when the user wants to close the window
	 * 
	 * @param e : WindowEvent
	 */
	public void windowClosing(WindowEvent e) {
		// TODO Auto-generated method stub
		int option = JOptionPane.showConfirmDialog(null, "Are you sure to want to quit ?", "Quit", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
		if(option == JOptionPane.OK_OPTION)
		{
			// clear the history
			clear();
			// if the user closes the window then disconnect him from the chat
			cgui.clickDisconnectButton();
		}
	}

	// Methods of the interfaces 
	public void mouseExited(MouseEvent e) {}
	public void mousePressed(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseReleased(MouseEvent e) {}
	public void windowDeactivated(WindowEvent e) {}
	public void windowDeiconified(WindowEvent e) {}
	public void windowIconified(WindowEvent e) {}
	public void windowOpened(WindowEvent e) {}
	public void windowActivated(WindowEvent e) {}
	public void windowClosed(WindowEvent e) {}

}
